/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.engine.runtime.jasper.ds;

import cn.easyplatform.contexts.RecordContext;
import cn.easyplatform.dos.FieldDo;

import java.math.BigDecimal;
import java.util.Comparator;
import java.util.Date;


/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
class RecordComparator implements Comparator<RecordContext> {

	private OrderField orderField;

	RecordComparator(OrderField orderField) {
		this.orderField = orderField;
	}

	@Override
	public int compare(RecordContext o1, RecordContext o2) {
		FieldDo fd1 = o1.getField(orderField.field);
		FieldDo fd2 = o2.getField(orderField.field);
		if (orderField.isDesc) {
			if (fd1.getValue() == null) {
				if (fd2.getValue() == null) {
					return 0;
				}
				return -1;
			} else if (fd2.getValue() == null) {
				return 1;
			}
			switch (fd1.getType()) {
			case INT:
			case LONG:
			case NUMERIC:
				BigDecimal bd1 = new BigDecimal(fd1.getValue().toString());
				BigDecimal bd2 = new BigDecimal(fd2.getValue().toString());
				return bd2.compareTo(bd1);
			case CHAR:
			case VARCHAR:
			case CLOB:
				return fd2.getValue().toString()
						.compareTo(fd1.getValue().toString());
			case DATETIME:
			case TIME:
			case DATE:
				Date date1 = (Date) fd1.getValue();
				Date date2 = (Date) fd2.getValue();
				return date2.compareTo(date1);
			case BOOLEAN:
				Boolean b1 = null;
				Boolean b2 = null;
				if (fd1.getValue() instanceof Boolean)
					b1 = (Boolean) fd1.getValue();
				else if (fd1.getValue() instanceof Number) {
					b1 = ((Number) fd1.getValue()).intValue() > 0 ? Boolean.TRUE
							: Boolean.FALSE;
				} else
					b1 = fd1.getValue().toString().equalsIgnoreCase("true");
				if (fd2.getValue() instanceof Boolean)
					b2 = (Boolean) fd2.getValue();
				else if (fd2.getValue() instanceof Number) {
					b2 = ((Number) fd2.getValue()).intValue() > 0 ? Boolean.TRUE
							: Boolean.FALSE;
				} else
					b2 = fd2.getValue().toString().equalsIgnoreCase("true");
				return b2.compareTo(b1);
			default:
				break;
			}
		} else {
			if (fd1.getValue() == null) {
				if (fd2.getValue() == null) {
					return 0;
				}
				return 1;
			} else if (fd2.getValue() == null) {
				return -1;
			}
			switch (fd1.getType()) {
			case INT:
			case LONG:
			case NUMERIC:
				BigDecimal bd1 = new BigDecimal(fd1.getValue().toString());
				BigDecimal bd2 = new BigDecimal(fd2.getValue().toString());
				return bd1.compareTo(bd2);
			case CHAR:
			case VARCHAR:
			case CLOB:
				return fd1.getValue().toString()
						.compareTo(fd2.getValue().toString());
			case DATETIME:
			case TIME:
			case DATE:
				Date date1 = (Date) fd1.getValue();
				Date date2 = (Date) fd2.getValue();
				return date1.compareTo(date2);
			case BOOLEAN:
				Boolean b1 = null;
				Boolean b2 = null;
				if (fd1.getValue() instanceof Boolean)
					b1 = (Boolean) fd1.getValue();
				else if (fd1.getValue() instanceof Number) {
					b1 = ((Number) fd1.getValue()).intValue() > 0 ? Boolean.TRUE
							: Boolean.FALSE;
				} else
					b1 = fd1.getValue().toString().equalsIgnoreCase("true");
				if (fd2.getValue() instanceof Boolean)
					b2 = (Boolean) fd2.getValue();
				else if (fd2.getValue() instanceof Number) {
					b2 = ((Number) fd2.getValue()).intValue() > 0 ? Boolean.TRUE
							: Boolean.FALSE;
				} else
					b2 = fd2.getValue().toString().equalsIgnoreCase("true");
				return b1.compareTo(b2);
			default:
				break;
			}
		}
		return 0;
	}

	static class OrderField {

		String field;

		boolean isDesc;

		public OrderField(String field, boolean isDesc) {
			this.field = field;
			this.isDesc = isDesc;
		}
	}
}
